#include <stdio.h>  /* -*- c -*- */
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <pthread.h>

#include <libspe2.h>
#include <malloc.h>

#cpu cell

#define SendInt(CTX, VAL)						\
  spe_in_mbox_write(CTX,    (unsigned int *) &VAL,			\
		    1, SPE_MBOX_ANY_NONBLOCKING);
#define GetInt(CTX, VAL)						\
  spe_out_intr_mbox_read(CTX,	(unsigned int *) &VAL,			\
			 1, SPE_MBOX_ALL_BLOCKING);
typedef int (*pifi)(int);
pifi multiplyFunc; 

pifi multiplyCompile(int multiplyValue)
{
  insn *code;

  posix_memalign(&code, 1024, 16);
  printf("Code generation for multiply value %d\n", multiplyValue);
  #[
	.org	code
	mpyi    $3, $3, (multiplyValue) 
	bi $lr 
  ]#;
  printf("Code generated\n");
  return (pifi)code;
}


void *waitingThread(void * arg)
{
  spe_program_handle_t *spu_handle;
  spe_stop_info_t stop_info;
  spe_context_ptr_t ctx = *(spe_context_ptr_t *) arg;  
  unsigned int entry = SPE_DEFAULT_ENTRY;

  /* Load wrapper SPU code */
  spu_handle = spe_image_open("simple-worker-cell");
  assert(NULL != spu_handle);
  spe_program_load(ctx, spu_handle);
  /* Send and launch the code */
  spe_context_run(ctx, &entry, 0, multiplyFunc, NULL, &stop_info);
  pthread_exit(0);
}

int main(int argc, char *argv[])
{
  pthread_t pthread;
  int i, a, res;
  spe_context_ptr_t ctx;

  if (argc < 2)
    {
      printf("%s [Multiply factor]\n", argv[0]);
      exit(0);
    }

  a = atoi (argv[1]);   /* Read data */
  multiplyFunc = multiplyCompile(a); /* Generate cell code depending on a value */
  ctx = spe_context_create(0, NULL);		 /* Send it to worker */
  pthread_create(&pthread, NULL, &waitingThread, &ctx);

  for (i = 1; i < 11; ++i)
    printf("%3d ", i);
  printf("\n");
  for (i = 1; i < 11; ++i)
    {
      SendInt(ctx, i);       	/* Send parameter */
      GetInt (ctx, res);	/* Get result */
      printf("%3d ", res);
    }
  printf("\n");
  /* Cleanup */
  spe_context_destroy(ctx);
  return 0;
}
